20
20
from monty .io import zopen
21
21
from monty .json import jsanitize
22
22
from monty .os .path import which
23
+ from monty .shutil import decompress_file
23
24
24
25
import numpy as np
25
26
28
29
from pymatgen .core .operations import SymmOp
29
30
from pymatgen .electronic_structure .bandstructure import BandStructureSymmLine
30
31
from pymatgen .symmetry .analyzer import SpacegroupAnalyzer
31
- from pymatgen .io .vasp import BSVasprun , Vasprun , Outcar , Locpot , Chgcar
32
+ from pymatgen .io .vasp import BSVasprun , Vasprun , Outcar , Locpot , Chgcar , \
33
+ parse_defect_states , Procar , Wavecar
32
34
from pymatgen .io .vasp .inputs import Poscar , Potcar , Incar , Kpoints
33
35
from pymatgen .apps .borg .hive import AbstractDrone
34
36
from pymatgen .command_line .bader_caller import bader_analysis_from_path
@@ -83,7 +85,8 @@ class VaspDrone(AbstractDrone):
83
85
84
86
def __init__ (self , runs = None , parse_dos = "auto" , bandstructure_mode = "auto" ,
85
87
parse_locpot = True , additional_fields = None , use_full_uri = True ,
86
- parse_bader = bader_exe_exists , parse_chgcar = False , parse_aeccar = False ):
88
+ parse_bader = bader_exe_exists , parse_chgcar = False , parse_aeccar = False ,
89
+ defect_wf_parsing = None ):
87
90
"""
88
91
Initialize a Vasp drone to parse vasp outputs
89
92
Args:
@@ -106,6 +109,10 @@ def __init__(self, runs=None, parse_dos="auto", bandstructure_mode="auto",
106
109
parse_bader (bool): Run and parse Bader charge data. Defaults to True if Bader is present
107
110
parse_chgcar (bool): Run and parse CHGCAR file
108
111
parse_aeccar (bool): Run and parse AECCAR0 and AECCAR2 files
112
+ defect_wf_parsing (Site): If Site is provided, drone considers Procar and
113
+ Wavecar parsing relative to the position of Site.
114
+ Useful for consideration of defect localization
115
+ Defaults to None (no extra procar or wavecar parsing occurs)
109
116
"""
110
117
self .parse_dos = parse_dos
111
118
self .additional_fields = additional_fields or {}
@@ -117,6 +124,7 @@ def __init__(self, runs=None, parse_dos="auto", bandstructure_mode="auto",
117
124
self .parse_bader = parse_bader
118
125
self .parse_chgcar = parse_chgcar
119
126
self .parse_aeccar = parse_aeccar
127
+ self .defect_wf_parsing = defect_wf_parsing
120
128
121
129
def assimilate (self , path ):
122
130
"""
@@ -210,6 +218,35 @@ def generate_doc(self, dir_name, vasprun_files, outcar_files):
210
218
logger .error ("Bad run stats for {}." .format (fullpath ))
211
219
d ["run_stats" ] = run_stats
212
220
221
+ # store defect localization/band filling information
222
+ if self .defect_wf_parsing :
223
+ # need to make sure all procars and wavecars are zipped
224
+ for propat in self .filter_files (fullpath , file_pattern = "PROCAR" ).values ():
225
+ decompress_file (os .path .join (fullpath , propat ))
226
+ for wavepat in self .filter_files (fullpath , file_pattern = "WAVECAR" ).values ():
227
+ decompress_file (os .path .join (fullpath , wavepat ))
228
+ procar_paths = [os .path .join (fullpath , ppath ) for ppath in
229
+ self .filter_files (fullpath , file_pattern = "PROCAR" ).values ()]
230
+ wavecar_paths = [os .path .join (fullpath , wpath ) for wpath in
231
+ self .filter_files (fullpath , file_pattern = "WAVECAR" ).values ()]
232
+
233
+ for i , d_calc in enumerate (d ["calcs_reversed" ]):
234
+ if d_calc .get ("output" ):
235
+ if len (procar_paths ) and len (wavecar_paths ):
236
+ procar = Procar (procar_paths [i ])
237
+ wavecar = Wavecar (wavecar_paths [i ])
238
+ structure = Structure .from_dict (d_calc ["output" ]["structure" ])
239
+ defect_data = parse_defect_states (structure , self .defect_wf_parsing , wavecar , procar )
240
+ d_calc ["output" ].update ({"defect" : defect_data })
241
+
242
+ filename = list (vasprun_files .values ())[i ]
243
+ vasprun_file = os .path .join (dir_name , filename )
244
+ vrun = Vasprun (vasprun_file )
245
+ eigenvalues = vrun .eigenvalues .copy ()
246
+ kpoint_weights = vrun .actual_kpoints_weights
247
+ vr_eigenvalue_dict = {'eigenvalues' : eigenvalues , 'kpoint_weights' : kpoint_weights }
248
+ d_calc ["output" ].update ({"vr_eigenvalue_dict" : vr_eigenvalue_dict })
249
+
213
250
# reverse the calculations data order so newest calc is first
214
251
d ["calcs_reversed" ].reverse ()
215
252
0 commit comments