Source code for dpgen.database.vasp
#/usr/bin/env python
# coding: utf-8
# Copyright (c) PThe Dpmodeling Team.
import os
import warnings
from monty.io import zopen
from monty.os.path import zpath
from monty.json import MSONable, MontyDecoder
from pymatgen.io.vasp import Potcar,Incar,Kpoints,Poscar,PotcarSingle
"""
Classes for reading/manipulating/writing VASP input files. All major VASP input
files.
"""
[docs]class DPPotcar(MSONable):
def __init__(self,symbols=None,functional="PBE",pp_file=None,pp_lists=None):
if pp_lists and pp_file is None:
for pp in pp_lists:
assert isinstance(pp,PotcarSingle)
self.potcars=pp_lists
elif pp_file and pp_list is None:
self.potcars=Potcar.from_file(pp_file)
elif pp_file and pp_list:
self.potcars=Potcar.from_file(pp_file)
else:
try:
self.potcars=Potcar(symbols=symbols, functional=functional)
except Exception:
warnings.warn ("""Inproperly configure of POTCAR !""")
self.potcars=None
if self.potcars is not None:
self.symbols = [pp.symbol for pp in self.potcars]
self.functional = list(set([pp.functional for pp in self.potcars]))[0]
self.hashs = [pp.get_potcar_hash() for pp in self.potcars]
else:
self.symbols=symbols
self.functional=functional
self.hashs = ''
self.elements = self._get_elements()
def __repr__(self):
return str(self)
def __str__(self):
if self.potcars is not None:
return str(self.potcars)
else:
ret ="Functional: %s\n"%self.functional
ret +=" ".join(self.symbols)+"\n"
return ret
def _get_elements(self):
elements=[]
for el in self.symbols:
if '_' in el:
elements.append(el.split('_')[0])
else:
elements.append(el)
return elements
[docs] @classmethod
def from_dict(cls,d):
return cls(symbols=d['symbols'],functional=d['functional'])
[docs] def as_dict(self):
d={}
d["@module"] = self.__class__.__module__
d["@class"] = self.__class__.__name__
d['symbols']=self.symbols
d['elements']=self.elements
d['hashs']=self.hashs
d['functional']=self.functional
return d
[docs] @classmethod
def from_file(cls,filename):
try:
potcars=Potcar.from_file(filename)
return cls(pp_lists=potcars)
except Exception:
with open(filename,'r') as f:
content=f.readlines()
functional=content[0].strip().split(':')[-1].strip()
symbols=content[1].strip().split()
return cls(symbols=symbols,functional=functional)
[docs]class VaspInput(dict, MSONable):
"""
Class to contain a set of vasp input objects corresponding to a run.
Args:
incar: Incar object.
kpoints: Kpoints object.
poscar: Poscar object.
potcar: Potcar object.
optional_files: Other input files supplied as a dict of {
filename: object}. The object should follow standard pymatgen
conventions in implementing a as_dict() and from_dict method.
"""
def __init__(self, incar, poscar, potcar, kpoints=None, optional_files=None,
**kwargs):
super().__init__(**kwargs)
self.update({'INCAR': incar,
'POSCAR': poscar,
'POTCAR': potcar})
if kpoints:
self.update({'KPOINTS': kpoints})
if optional_files is not None:
self.update(optional_files)
def __str__(self):
output = []
for k, v in self.items():
output.append(k)
output.append(str(v))
output.append("")
return "\n".join(output)
[docs] def as_dict(self):
d = {k: v.as_dict() for k, v in self.items()}
d["@module"] = self.__class__.__module__
d["@class"] = self.__class__.__name__
return d
[docs] @classmethod
def from_dict(cls, d):
dec = MontyDecoder()
sub_d = {"optional_files": {}}
for k, v in d.items():
if k in ["INCAR", "POSCAR", "POTCAR", "KPOINTS"]:
sub_d[k.lower()] = dec.process_decoded(v)
elif k not in ["@module", "@class"]:
sub_d["optional_files"][k] = dec.process_decoded(v)
return cls(**sub_d)
[docs] def write_input(self, output_dir=".", make_dir_if_not_present=True):
"""
Write VASP input to a directory.
Args:
output_dir (str): Directory to write to. Defaults to current
directory (".").
make_dir_if_not_present (bool): Create the directory if not
present. Defaults to True.
"""
if make_dir_if_not_present and not os.path.exists(output_dir):
os.makedirs(output_dir)
for k, v in self.items():
with zopen(os.path.join(output_dir, k), "wt") as f:
f.write(v.__str__())
[docs] @staticmethod
def from_directory(input_dir, optional_files=None):
"""
Read in a set of VASP input from a directory. Note that only the
standard INCAR, POSCAR, POTCAR and KPOINTS files are read unless
optional_filenames is specified.
Args:
input_dir (str): Directory to read VASP input from.
optional_files (dict): Optional files to read in as well as a
dict of {filename: Object type}. Object type must have a
static method from_file.
"""
sub_d = {}
try:
for fname, ftype in [("INCAR", Incar), ("KPOINTS", Kpoints),
("POSCAR", Poscar), ("POTCAR", DPPotcar)]:
fullzpath = zpath(os.path.join(input_dir, fname))
sub_d[fname.lower()] = ftype.from_file(fullzpath)
except Exception:
for fname, ftype in [("INCAR", Incar),
("POSCAR", Poscar), ("POTCAR", DPPotcar)]:
fullzpath = zpath(os.path.join(input_dir, fname))
sub_d[fname.lower()] = ftype.from_file(fullzpath)
sub_d["optional_files"] = {}
if optional_files is not None:
for fname, ftype in optional_files.items():
sub_d["optional_files"][fname] = \
ftype.from_file(os.path.join(input_dir, fname))
return VaspInput(**sub_d)