Source code for dpgen2.fp.vasp_input
from pathlib import (
Path,
)
from typing import (
Dict,
List,
Optional,
Set,
Tuple,
Union,
)
import dpdata
import numpy as np
from dargs import (
Argument,
ArgumentEncoder,
Variant,
dargs,
)
[docs]
class VaspInputs:
def __init__(
self,
kspacing: Union[float, List[float]],
incar: str,
pp_files: Dict[str, str],
kgamma: bool = True,
):
"""
Parameters
----------
kspacing : Union[float, List[float]]
The kspacing. If it is a number, then three directions use the same
ksapcing, otherwise it is a list of three numbers, specifying the
kspacing used in the x, y and z dimension.
incar : str
A template INCAR file.
pp_files : Dict[str,str]
The potcar files for the elements. For example
{
"H" : "/path/to/POTCAR_H",
"O" : "/path/to/POTCAR_O",
}
kgamma : bool
K-mesh includes the gamma point
"""
self.kspacing = kspacing
self.kgamma = kgamma
self.incar_from_file(incar)
self.potcars_from_file(pp_files)
@property
def incar_template(self):
return self._incar_template
@property
def potcars(self):
return self._potcars
[docs]
def potcars_from_file(
self,
dict_fnames: Dict[str, str],
):
self._potcars = {}
for kk, vv in dict_fnames.items():
self._potcars[kk] = Path(vv).read_text()
[docs]
def make_potcar(
self,
atom_names,
) -> str:
potcar_contents = []
for nn in atom_names:
potcar_contents.append(self._potcars[nn])
return "".join(potcar_contents)
[docs]
def make_kpoints(
self,
box: np.ndarray,
) -> str:
return make_kspacing_kpoints(box, self.kspacing, self.kgamma)
[docs]
@staticmethod
def args():
doc_pp_files = 'The pseudopotential files set by a dict, e.g. {"Al" : "path/to/the/al/pp/file", "Mg" : "path/to/the/mg/pp/file"}'
doc_incar = "The path to the template incar file"
doc_kspacing = "The spacing of k-point sampling. `ksapcing` will overwrite the incar template"
doc_kgamma = "If the k-mesh includes the gamma point. `kgamma` will overwrite the incar template"
return [
Argument("incar", str, optional=False, doc=doc_incar),
Argument("pp_files", dict, optional=False, doc=doc_pp_files),
Argument("kspacing", float, optional=False, doc=doc_kspacing),
Argument("kgamma", bool, optional=True, default=True, doc=doc_kgamma),
]
[docs]
@staticmethod
def normalize_config(data={}, strict=True):
ta = VaspInputs.args()
base = Argument("base", dict, ta)
data = base.normalize_value(data, trim_pattern="_*")
base.check_value(data, strict=strict)
return data
[docs]
def make_kspacing_kpoints(box, kspacing, kgamma):
if type(kspacing) is not list:
kspacing = [kspacing, kspacing, kspacing]
box = np.array(box)
rbox = _reciprocal_box(box)
kpoints = [
max(1, (np.ceil(2 * np.pi * np.linalg.norm(ii) / ks).astype(int)))
for ii, ks in zip(rbox, kspacing) # type: ignore
]
ret = _make_vasp_kpoints(kpoints, kgamma)
return ret
def _make_vasp_kp_gamma(kpoints):
ret = ""
ret += "Automatic mesh\n"
ret += "0\n"
ret += "Gamma\n"
ret += "%d %d %d\n" % (kpoints[0], kpoints[1], kpoints[2])
ret += "0 0 0\n"
return ret
def _make_vasp_kp_mp(kpoints):
ret = ""
ret += "K-Points\n"
ret += "0\n"
ret += "Monkhorst Pack\n"
ret += "%d %d %d\n" % (kpoints[0], kpoints[1], kpoints[2])
ret += "0 0 0\n"
return ret
def _make_vasp_kpoints(kpoints, kgamma=False):
if kgamma:
ret = _make_vasp_kp_gamma(kpoints)
else:
ret = _make_vasp_kp_mp(kpoints)
return ret
def _reciprocal_box(box):
rbox = np.linalg.inv(box)
rbox = rbox.T
return rbox