def cli(input_file: Path, output_directory: Path, verbose: bool) -> None: ''' Converts the VASP WAVECAR to UNK files for wannier90. Args: input_file (Path): path to WAVECAR file (default='./WAVECAR') output_directory (Path): directory where UNKs ar ewritten (default = .) verbose (bool): verbose output (default = False) ''' Wavecar(input_file, verbose=verbose).write_unks(output_directory)
def read_WAVECAR(file='WAVECAR', ks=0, bs=1, s=0, output='wf'): # The list of coefficients for each k-point and band for reconstructing the wavefunction. # For non-spin-polarized, the first index corresponds to the kpoint and the second corresponds to the band # (e.g. self.coeffs[kp][b] corresponds to k-point kp and band b). # For spin-polarized calculations, the first index is for the spin. wavecar = Wavecar(file) for k in ks: for b in bs: #wf = wavecar.fft_mesh(kpoint=k, band=b-1) coeffs = np.array(wavecar.coeffs) if coeffs.ndim == 3: wf = coeffs[s][k][b] else: wf = coeffs[k][b] print('wf.shape', wf.shape) print('wavecar.kpoints', wavecar.kpoints) np.save('{}_k{}b{}.npy'.format(output, k, b), wf)
def get_Wif_from_wavecars( wavecars: List, init_wavecar_path: str, def_index: int, bulk_index: Sequence[int], spin: int = 0, kpoint: int = 1, fig=None ) -> List: """Compute the electron-phonon matrix element using the WAVECARs. This function reads in the pseudo-wavefunctions from the WAVECAR files and computes the overlaps necessary. *** WARNING: USE AT YOUR OWN RISK *** Because these are pseudo-wavefunctions, the core information from the PAWs is missing. As a result, the resulting Wif value may be unreliable. A good test of this is how close the Q=0 overlap is to 0. (it would be exactly 0. if you include the corrections from the PAWs). This should only be used to get a preliminary idea of the Wif value. *************** Parameters ---------- wavecars : list((Q, wavecar_path)) a list of tuples where the first value is the Q and the second is the path to the WAVECAR file init_wavecar_path : string path to the initial wavecar for computing overlaps def_index : int index corresponding to the defect wavefunction (1-based indexing) bulk_index : int, list(int) index or list of indices corresponding to the bulk wavefunction (1-based indexing) spin : int spin channel to read from (0 - up, 1 - down) kpoint : int kpoint to read from (defaults to the first kpoint) fig : matplotlib.figure.Figure optional figure object to plot diagnostic information Returns ------- list((bulk_index, Wif)) electron-phonon matrix element Wif in units of eV amu^{-1/2} Angstrom^{-1} for each bulk_index """ bulk_index = np.array(bulk_index) initial_wavecar = Wavecar(init_wavecar_path) if initial_wavecar.spin == 2: psi_i = initial_wavecar.coeffs[spin][kpoint-1][def_index-1] else: psi_i = initial_wavecar.coeffs[kpoint-1][def_index-1] Nw, Nbi = (len(wavecars), len(bulk_index)) Q, matels, deig = (np.zeros(Nw+1), np.zeros((Nbi, Nw+1)), np.zeros(Nbi)) # first compute the Q = 0 values and eigenvalue differences for i, bi in enumerate(bulk_index): if initial_wavecar.spin == 2: psi_f = initial_wavecar.coeffs[spin][kpoint-1][bi-1] deig[i] = initial_wavecar.band_energy[spin][kpoint-1][bi-1][0] - \ initial_wavecar.band_energy[spin][kpoint-1][def_index-1][0] else: psi_f = initial_wavecar.coeffs[kpoint-1][bi-1] deig[i] = initial_wavecar.band_energy[kpoint-1][bi-1][0] - \ initial_wavecar.band_energy[kpoint-1][def_index-1][0] matels[i, Nw] = _compute_matel(psi_i, psi_f) deig = np.abs(deig) # now compute for each Q for i, (q, fname) in enumerate(wavecars): Q[i] = q final_wavecar = Wavecar(fname) for j, bi in enumerate(bulk_index): if final_wavecar.spin == 2: psi_f = final_wavecar.coeffs[spin][kpoint-1][bi-1] else: psi_f = final_wavecar.coeffs[kpoint-1][bi-1] matels[j, i] = _compute_matel(psi_i, psi_f) if fig is not None: ax = fig.subplots(1, Nbi) ax = np.array(ax) for a, i in zip(ax, range(Nbi)): a.scatter(Q, matels[i, :]) a.set_title(f'{bulk_index[i]}') return [(bi, deig[i] * np.mean(np.abs(np.gradient(matels[i, :], Q)))) for i, bi in enumerate(bulk_index)]
from pymatgen.symmetry.analyzer import SpacegroupAnalyzer from matplotlib import pyplot as plt from pymatgen.ext.matproj import MPRester from pymatgen.io.vasp.inputs import Poscar from pymatgen.io.cif import CifWriter from pymatgen.cli.pmg_plot import get_chgint_plot from pymatgen.io.vasp.outputs import Chgcar,Wavecar,VolumetricData,Procar,Elfcar import os from pymatgen.util.plotting import pretty_plot dire = r'D:\Desktop\合作计算数据\数据\FeS101-O2' os.chdir(dire) print (os.getcwd()) wavecar = Wavecar(filename ='WAVECAR') poscar = Poscar.from_file("POSCAR") chgcar = wavecar.get_parchg(poscar,0,1) # procar = Procar('PROCAR') # data = procar.data struct = poscar.structure s = chgcar.structure finder = SpacegroupAnalyzer(s, symprec=0.1) sites = [sites[0] for sites in finder.get_symmetrized_structure().equivalent_sites] atom_ind = [s.sites.index(site) for site in sites] for i in atom_ind: d = chgcar.get_integrated_diff(i, 1, 30) plt.plot(d[:, 0], d[:, 1], label="Atom {} - {}".format(i, s[i].species_string)) plt.legend(loc="upper left") plt.xlabel("Radius (A)")
def overlap_so_spinpol(self): """ Main function to calculate SOC spillage """ noso = Wavecar(self.wf_noso) so = Wavecar(self.wf_so) bcell = np.linalg.inv(noso.a).T tmp = np.linalg.norm(np.dot(np.diff(noso.kpoints, axis=0), bcell), axis=1) noso_k = np.concatenate(([0], np.cumsum(tmp))) noso_bands = np.array(noso.band_energy)[:, :, :, 0] noso_kvecs = np.array(noso.kpoints) noso_occs = np.array(noso.band_energy)[:, :, :, 2] noso_nkpts = len(noso_k) bcell = np.linalg.inv(so.a).T tmp = np.linalg.norm(np.dot(np.diff(so.kpoints, axis=0), bcell), axis=1) so_k = np.concatenate(([0], np.cumsum(tmp))) so_bands = np.array([np.array(so.band_energy)[:, :, 0]]) so_kvecs = np.array(so.kpoints) # so_occs = np.array([np.array(so.band_energy)[:, :, 2]]) so_nkpts = len(so_k) nelec_list = [] for nk1 in range(1, noso_nkpts + 1): # no spin orbit kpoints loop knoso = noso_kvecs[nk1 - 1, :] for nk2 in range(1, so_nkpts + 1): # spin orbit kso = so_kvecs[nk2 - 1, :] if (self.isclose(kso[0], knoso[0]) and self.isclose(kso[1], knoso[1]) and self.isclose( kso[2], knoso[2])): # do kpoints match? for c, e in enumerate(noso_occs[0, nk1 - 1, :]): if e < 0.5: cup = c break for c, e in enumerate(noso_occs[1, nk1 - 1, :]): if e < 0.5: cdn = c break nelec_list.append([cup, cdn, cup + cdn]) n_arr = np.array(nelec_list) n_up = int(round(np.mean(n_arr[:, 0]))) n_dn = int(round(np.mean(n_arr[:, 1]))) n_tot = int(round(np.mean(n_arr[:, 2]))) nelec = int(n_tot) # noso_homo_up = np.max(noso_bands[0, :, n_up - 1]) # noso_lumo_up = np.min(noso_bands[0, :, n_up]) # noso_homo_dn = np.max(noso_bands[1, :, n_dn - 1]) # noso_lumo_dn = np.min(noso_bands[1, :, n_dn]) so_homo = np.max(so_bands[0, :, nelec - 1]) so_lumo = np.min(so_bands[0, :, nelec]) # noso_direct_up = np.min(noso_bands[0, :, n_up] - noso_bands[0, :, n_up - 1]) # noso_direct_dn = np.min(noso_bands[1, :, n_dn] - noso_bands[1, :, n_dn - 1]) so_direct = np.min(so_bands[0, :, nelec] - so_bands[0, :, nelec - 1]) noso_direct = 1000000.0 noso_homo = -10000000.0 noso_lumo = 100000000.0 for i in range(noso_bands.shape[1]): homo_k = max(noso_bands[0, i, n_up - 1], noso_bands[1, i, n_dn - 1]) lumo_k = min(noso_bands[0, i, n_up], noso_bands[1, i, n_dn]) noso_direct = min(noso_direct, lumo_k - homo_k) noso_homo = max(noso_homo, homo_k) noso_lumo = min(noso_lumo, lumo_k) gamma_k = [] kpoints = [] np.set_printoptions(precision=4) x = [] y = [] nelec_tot = 0.0 for nk1 in range(1, noso_nkpts + 1): # no spin orbit kpoints loop knoso = noso_kvecs[nk1 - 1, :] for nk2 in range(1, so_nkpts + 1): # spin orbit kso = so_kvecs[nk2 - 1, :] if (self.isclose(kso[0], knoso[0]) and self.isclose(kso[1], knoso[1]) and self.isclose( kso[2], knoso[2])): # do kpoints match? # changes section 2 nelec_up = n_arr[nk1 - 1, 0] nelec_dn = n_arr[nk1 - 1, 1] nelec_tot = n_arr[nk1 - 1, 2] kpoints.append(kso) Mmn = 0.0 vnoso = np.array( noso.coeffs[0][nk1 - 1][0] ) # noso.readBandCoeff(ispin=1, ikpt=nk1, iband=1, norm=False) n_noso1 = vnoso.shape[0] vnoso = np.array( noso.coeffs[1][nk1 - 1][0] ) # noso.readBandCoeff(ispin=2, ikpt=nk1, iband=1, norm=False) # n_noso2 = vnoso.shape[0] vso = so.coeffs[nk1 - 1][0].flatten( ) # so.readBandCoeff(ispin=1, ikpt=nk2, iband=1, norm=False) n_so = vso.shape[0] vs = min(n_noso1 * 2, n_so) Vnoso = np.zeros((vs, nelec_tot), dtype=complex) Vso = np.zeros((vs, nelec_tot), dtype=complex) if np.array(noso.coeffs[1][nk1 - 1]).shape[1] == vs // 2: # if nk1==10 and nk2==10: # print (np.array(noso.coeffs[1][nk1-1]).shape[1], ) # prepare matricies for n1 in range(1, nelec_up + 1): Vnoso[0:vs // 2, n1 - 1] = np.array( noso.coeffs[0][nk1 - 1][n1 - 1])[0:vs // 2] for n1 in range(1, nelec_dn + 1): Vnoso[vs // 2:vs, n1 - 1 + nelec_up] = np.array( noso.coeffs[1][nk1 - 1][n1 - 1])[0:vs // 2] for n1 in range(1, nelec_tot + 1): t = so.coeffs[nk2 - 1][n1 - 1].flatten() Vso[0:vs // 2, n1 - 1] = t[0:vs // 2] Vso[vs // 2:vs, n1 - 1] = t[n_so // 2:n_so // 2 + vs // 2] Qnoso, num_noso = self.orth( Vnoso) # make orthonormal basis? Qso, num_so = self.orth(Vso) gamma_k.append(nelec_tot) a = [] for n1 in range(0, nelec_tot): # noso occupied bands v1 = Qnoso[:, n1] aa = 0.0 for n2 in range(0, nelec_tot): # so occupied bands v2 = Qso[:, n2] t = np.dot(np.conj(v1), v2) Mmn += t * t.conj() aa += (t * t.conj()).real a.append(aa) gamma_k[-1] -= Mmn # eq 4 in prb 90 125133 x.append(kso) y.append(np.real(gamma_k[-1])) if gamma_k[-1] > 0.5: print( "nk1 nk2 kpoint gamma_k ", nk1, nk2, kso, knoso, np.real(gamma_k[-1]), "!!!!!!!!!!", ) gmax = max(np.real(gamma_k)) nkmax = np.argmax(np.real(gamma_k)) kmax = kpoints[nkmax] print("------------------------------------") print() print(" INDIRECT DIRECT H**O/LUMO (eV)") print( "no spin-orbit gaps", "{:+.3f}".format(float(noso_lumo - noso_homo)), "{:+.3f}".format(noso_direct), " ", [noso_homo, noso_lumo], ) print( "spin-orbit gaps ", "{:+.3f}".format(float(so_lumo - so_homo)), "{:+.3f}".format(so_direct), " ", [so_homo, so_lumo], ) print("gamma max", np.real(gmax), " at k = ", kmax) return gmax
def charged_supercell_scaling_VASP(wavecar_path: str, bulk_index: int, def_index: int = -1, def_coord: Optional[np.ndarray] = None, cutoff: float = 0.02, limit: float = 5., spin: int = 0, kpoint: int = 1, fig=None, full_range=False) -> float: """ Estimate the interaction between the defect and bulk wavefunction. This function estimates the interaction between the defect and bulk wavefunction due to spurious effects as a result of using a charged supercell. The radial distribution of the bulk wavefunction is compared to a perfectly homogenous wavefunction to estimate the scaling. Either def_index or def_coord must be specified. If you get wonky results with def_index, try using def_coord as there may be a problem with finding the defect position if the defect charge is at the boundary of the cell. Parameters ---------- wavecar_path : str path to the WAVECAR file that contains the relevant wavefunctions def_index, bulk_index : int index of the defect and bulk wavefunctions in the WAVECAR file def_coord : np.array(dim=(3,)) cartesian coordinates of defect position cutoff : float cutoff for determining zero slope regions limit : float upper limit for windowing procedure spin : int spin channel to read from (0 - up, 1 - down) kpoint : int kpoint to read from (defaults to the first kpoint) fig : matplotlib.figure.Figure optional figure object to plot diagnostic information (recommended) full_range : bool determines if full range of first plot is shown Returns ------- float estimated scaling value to apply to the capture coefficient """ if def_index == -1 and def_coord is None: raise ValueError('either def_index or def_coord must be specified') wavecar = Wavecar(wavecar_path) # compute relevant things if def_coord is None: psi_def = wavecar.fft_mesh(spin=spin, kpoint=kpoint - 1, band=def_index - 1) fft_psi_def = np.fft.ifftn(psi_def) den_def = np.abs(np.conj(fft_psi_def) * fft_psi_def) / \ np.abs(np.vdot(fft_psi_def, fft_psi_def)) def_coord = find_charge_center(den_def, wavecar.a) psi_bulk = wavecar.fft_mesh(spin=spin, kpoint=kpoint - 1, band=bulk_index - 1) fft_psi_bulk = np.fft.ifftn(psi_bulk) return charged_supercell_scaling(fft_psi_bulk, wavecar.a, def_coord, cutoff=cutoff, limit=limit, fig=fig, full_range=full_range)
from pymatgen.io.vasp.outputs import Wavecar, Vasprun, Chgcar from pymatgen.io.vasp.inputs import Poscar wc = Wavecar() poscar = Poscar.from_file('CONTCAR') kpoint = 0 band = 126 # chosen reading PROCAR file for kpoint Gamma. Partial DOS of d-orbitals big "enough" chgcar = wc.get_parchg(poscar, kpoint, band) chgcar.write_file('CHGCAR_k0_band126.vasp')
from pymatgen.io.vasp.outputs import Wavecar import os if __name__ == '__main__': os.chdir('/home/jinho93/tmdc/mos2/2h/hse/bulk/dos') wave = Wavecar() print(wave) print(len(wave.coeffs[0][0]))