def parse_psp(files: typ.Dict[str, str], dftcode: str) -> str: """ Returns simplified string representation of the pseudopotnetial used in a DFT calculation """ if dftcode == 'vasp': return '{}' #ideally we parse the potcar to reconstruct setups dictionary elif dftcode == 'gpaw': log = files.get('log', '') pspth = parse_line(log, 'setups', 0).split(': ')[-1].strip() elif dftcode == 'quantumespresso': pwinp = files.get('pwinp', '') pspth = parse_line(pwinp, 'pseudo_dir', 0).split("='")[1][:-2] else: raise NotImplementedError("new dftcode? ", dftcode) if 'gbrv' in pspth: return 'gbrv15pbe' elif 'dacapo' in pspth: return 'dacapo' elif 'sg15' in pspth: return 'sg15' elif 'paw' in pspth: if 'gpaw-setups-0.6.6300' in log: return 'oldpaw' else: return 'paw' else: raise NotImplementedError('New psp? path = ', pspth)
def parse_xc(files: typ.Dict[str, str], dftcode: str) -> str: """ Finds the exchange correlation functional """ log = files.get('log') pwinp = files.get('pwinp') incar = files.get('incar') if dftcode == 'gpaw': xc = parse_line(log, 'xc:', 0).split(':')[-1].strip() elif dftcode == 'quantumespresso': xc = parse_line(pwinp, 'input_dft', 0).split('=')[-1].replace(',', '').replace("'", '').strip() elif dftcode == 'vasp': if parse_line(incar, 'GGA', 0).split('=')[-1].strip() == 'PE': if True: #if not BEEF? xc = 'PBE' else: raise NotImplementedError('New functional in vasp?') else: raise NotImplementedError('New DFT code? ' + dftcode) if xc.lower() == 'pbe': return 'PBE' elif xc.lower() in ['beef', 'beef-vdw']: return 'BEEF' elif xc.lower() == 'rpbe': return 'RPBE' elif xc.lower() == 'mbeef': return 'mBEEF' else: raise ValueError("weird xc: ", xc)
def get_sigma(dftcode : str ,files : typ.Dict[str,str] ) -> typ.Optional[float]: """ Helpful docstring """ if dftcode == 'gpaw': log = files['log'] parsed = parse_line(log,'Fermi-Dirac',0) raw = parsed.split('=')[1].split()[0] return float(raw) elif dftcode == 'quantumespresso': pwinp = files['pwinp'] parsed = parse_line(pwinp,'degauss',0) raw = parsed.split('=')[1][:7] return round(13.60569 * float(raw),3) elif dftcode == 'vasp': incar = files['incar'] parsed = parse_line(incar,'SIGMA',0) raw = parsed.split('=')[-1] return float(raw) else: raise NotImplementedError
def get_econv(dftcode: str, files: typ.Dict[str, str]) -> typ.Optional[float]: """ Docstring """ if dftcode == 'gpaw': log = files['log'] parsed = parse_line(log, 'convergence:', 0) raw = parsed.split('energy:')[-1] pure = raw.replace('}', '') return float(pure) elif dftcode == 'quantumespresso': pwinp = files['pwinp'] try: line = parse_line(pwinp, 'conv_thr', -1) except IndexError: raise ValueError('Problem with parse line') raw = line.split('=')[1][:-1] return round(13.60569 * float(raw), 6) elif dftcode == 'vasp': incar = files['incar'] parsed = parse_line(incar, 'EDIFF', 0) raw = parsed.split('=')[-1] return float(raw) else: raise NotImplementedError("Unknown dft code?")
def get_vasp_key(dftcode : str ,files : typ.Dict[str,str] ,key : str ,dtype : str ) -> typ.Optional[typ.Union[int,str,float]]: """ common form of extracting VASP input info """ assert dtype in cast_maybe.keys(), 'bad dtype argument for get_vasp_key: '+dtype if dftcode =='vasp': incar = files['incar'] try: parsed = parse_line(incar,key,0).split('=')[-1].strip() except IndexError: parsed = None # type: ignore return cast_maybe[dtype](parsed) # type: ignore else: return None
def get_kpts(dftcode: str, files: typ.Dict[str, str]) -> typ.Tuple[int, int, int]: """ docstring """ if dftcode == 'gpaw': log = files['log'] parsed = parse_line(log, 'kpts') raw = parsed.split(': ')[-1].split() pure = ','.join(raw) return tuple(ast.literal_eval(pure)) #type: ignore elif dftcode == 'quantumespresso': pwinp = files['pwinp'] line = pwinp.split('\n')[-2] raw = line.split()[:3] return tuple([int(x) for x in raw]) #type: ignore elif dftcode == 'vasp': kptcar = files['kptcar'] line = kptcar.split('\n')[-2] raw = [int(x) for x in line.split()] return tuple(raw) #type: ignore else: raise NotImplementedError('new dftcode? ', dftcode)
def get_nmix(dftcode: str, files: typ.Dict[str, str]) -> typ.Optional[float]: """ Docstring """ if dftcode == 'gpaw': log = files['log'] parsed = parse_line(log, 'nmaxold', 0) raw = parsed.split(':')[1].replace(',', '') return float(raw) elif dftcode == 'quantumespresso': pwinp = files['pwinp'] parsed = parse_line(pwinp, 'mixing_ndim', 0) raw = parsed.split("=")[1][:-1] return round(float(raw), 3) else: return None
def get_dw(dftcode: str, files: typ.Dict[str, str]) -> typ.Optional[int]: """ Docstring """ if dftcode == 'quantumespresso': pwinp = files['pwinp'] parsed = parse_line(pwinp, 'ecutrho', 0) raw = parsed.split('=')[1][:7] return round(13.60569 * float(raw)) else: return None
def get_mixtype(dftcode: str, files: typ.Dict[str, str]) -> typ.Optional[str]: """ Helpful docstring """ if dftcode == 'quantumespresso': log = files['log'] parsed = parse_line(log, 'number of iterations used', 0) return parsed.split()[6] else: return None
def get_fmax(dftcode: str, paramsdict: str, files: typ.Dict[str, str]) -> typ.Optional[float]: """ docstring """ if dftcode == 'vasp': incar = files['incar'] return -float(parse_line(incar, 'EDIFFG', 0).split('=')[-1]) else: params = json.loads(paramsdict) return params.get( 'fmax') # no conceivable way of getting this from log
def get_diag(dftcode: str, files: typ.Dict[str, str]) -> typ.Optional[float]: """ Docstring """ if dftcode == 'gpaw': log = files['log'] parsed = parse_line(log, 'eigensolver', 0) eigenline = parsed.split(': ')[-1] if 'dav' in eigenline: return 'david' else: return eigenline elif dftcode == 'quantumespresso': pwinp = files['pwinp'] parsed = parse_line(pwinp, 'diagonalization', 0) return parsed.split("='")[1][:-2] else: return None
def get_nbands(dftcode : str ,paramsdict : str ,files : typ.Dict[str,str] ) -> typ.Optional[float]: """ docstring """ if dftcode == 'vasp': outcar = files['outcar'] return int(parse_line(outcar,'NBANDS',0).split('=')[-1]) else: params = json.loads(paramsdict) return params.get('fmax') # no conceivable way of getting this from log
def get_maxstep(dftcode : str ,files : typ.Dict[str,str] ) -> int : """ Helpful docstring """ if dftcode == 'gpaw': log = files['log'] parsed = parse_line(log,'maxiter',0) return int(parsed.split(':')[-1]) elif dftcode == 'quantumespresso': pwinp = files['pwinp'] parsed = parse_line(pwinp,'electron_maxstep',0) return int(parsed.split('=')[1][:-1]) elif dftcode == 'vasp': incar = files['incar'] parsed = parse_line(incar,'NELM',0) return int(parsed.split('=')[-1]) else: raise NotImplementedError
def parse_pw(files: typ.Dict[str, str], dftcode: str) -> int: """ Using "dftcode" as a switch, choose an appropriate file from a directory and parse it for the planewave cutoff (in eV). files - a dictionary mapping file names to file content dftcode - must be one of {gpaw,vasp,quantumespresso} parse_line - args are: haystack,needle,n - returns: the Nth line of a haystack that contains the needle """ # Constants #---------- RYDBERG_TO_EV = 13.60569 # Parsing #------- if dftcode == 'gpaw': log = files.get('log') parsed = parse_line(log, 'ecut', 0) raw_num = parsed.split()[-1].replace(',', '') elif dftcode == 'quantumespresso': pwinp = files.get('pwinp') parsed = parse_line(pwinp, 'ecutwfc', 0) raw_rydberg = parsed.split('=')[1][:7] raw_num = RYDBERG_TO_EV * float(raw_rydberg) elif dftcode == 'vasp': incar = files.get('incar') parsed = parse_line(incar, 'ENCUT', 0) raw_num = parsed.split('=')[-1] else: raise ValueError('new dftcode? ', dftcode) return int(round(float(raw_num)))
def get_dipol(dftcode: str, files: typ.Dict[str, str]) -> typ.Optional[str]: """ Docstring """ if dftcode == 'vasp': incar = files['incar'] for l in incar.split('\n'): if 'DIPOL' in l and 'LDIPOL' not in l: line = parse_line(incar, '\nDIPOL', 0) raw = line.split('=')[-1].split() output = [float(x) for x in raw] return json.dumps(output) return None else: return None
def get_dipole(dftcode: str, files: typ.Dict[str, str]) -> int: """ Docstring """ if dftcode == 'gpaw': return 0 elif dftcode == 'quantumespresso': pwinp = files['pwinp'] return int('dipfield=.true.' in pwinp) elif dftcode == 'vasp': incar = files['incar'] parsed = parse_line(incar, 'LDIPOL', 0) return int('TRUE' in parsed) else: raise NotImplementedError
def getENG_QE(log: str) -> float: e = float(parse_line(log, 'total energy', -2).split()[-2]) ts = float(parse_line(log, 'smearing contrib.', -1).split()[-2]) return (e - ts / 2) * 13.6057
def getENG_GPAW(log: str) -> float: return float(parse_line(log, 'Extrapolated:', -1).split()[-1])
def getENG_VASP(log: str) -> float: return float(parse_line(log, 'energy(sigma->0)', -1).split()[-1])