Source code for dpdata.plugins.vasp

import numpy as np

import dpdata.vasp.outcar
import dpdata.vasp.poscar
import dpdata.vasp.xml
from dpdata.format import Format
from dpdata.utils import uniq_atom_names


[docs] @Format.register("poscar") @Format.register("contcar") @Format.register("vasp/poscar") @Format.register("vasp/contcar") class VASPPoscarFormat(Format):
[docs] @Format.post("rot_lower_triangular") def from_system(self, file_name, **kwargs): with open(file_name) as fp: lines = [line.rstrip("\n") for line in fp] data = dpdata.vasp.poscar.to_system_data(lines) data = uniq_atom_names(data) return data
[docs] def to_system(self, data, file_name, frame_idx=0, **kwargs): """Dump the system in vasp POSCAR format. Parameters ---------- data : dict The system data file_name : str The output file name frame_idx : int The index of the frame to dump **kwargs : dict other parameters """ w_str = VASPStringFormat().to_system(data, frame_idx=frame_idx) with open(file_name, "w") as fp: fp.write(w_str)
[docs] @Format.register("vasp/string") class VASPStringFormat(Format):
[docs] def to_system(self, data, frame_idx=0, **kwargs): """Dump the system in vasp POSCAR format string. Parameters ---------- data : dict The system data frame_idx : int The index of the frame to dump **kwargs : dict other parameters """ assert frame_idx < len(data["coords"]) return dpdata.vasp.poscar.from_system_data(data, frame_idx)
# rotate the system to lammps convention
[docs] @Format.register("outcar") @Format.register("vasp/outcar") class VASPOutcarFormat(Format):
[docs] @Format.post("rot_lower_triangular") def from_labeled_system( self, file_name, begin=0, step=1, convergence_check=True, **kwargs ): data = {} ml = kwargs.get("ml", False) ( data["atom_names"], data["atom_numbs"], data["atom_types"], data["cells"], data["coords"], data["energies"], data["forces"], tmp_virial, ) = dpdata.vasp.outcar.get_frames( file_name, begin=begin, step=step, ml=ml, convergence_check=convergence_check, ) if tmp_virial is not None: data["virials"] = tmp_virial # scale virial to the unit of eV if "virials" in data: v_pref = 1 * 1e3 / 1.602176621e6 for ii in range(data["cells"].shape[0]): vol = np.linalg.det(np.reshape(data["cells"][ii], [3, 3])) data["virials"][ii] *= v_pref * vol data = uniq_atom_names(data) return data
# rotate the system to lammps convention
[docs] @Format.register("xml") @Format.register("vasp/xml") class VASPXMLFormat(Format):
[docs] @Format.post("rot_lower_triangular") def from_labeled_system(self, file_name, begin=0, step=1, **kwargs): data = {} ( data["atom_names"], data["atom_types"], data["cells"], data["coords"], data["energies"], data["forces"], tmp_virial, ) = dpdata.vasp.xml.analyze( file_name, type_idx_zero=True, begin=begin, step=step ) data["atom_numbs"] = [] for ii in range(len(data["atom_names"])): data["atom_numbs"].append(sum(data["atom_types"] == ii)) # the vasp xml assumes the direct coordinates # apply the transform to the cartesan coordinates for ii in range(data["cells"].shape[0]): data["coords"][ii] = np.matmul(data["coords"][ii], data["cells"][ii]) # scale virial to the unit of eV if tmp_virial.size > 0: data["virials"] = tmp_virial v_pref = 1 * 1e3 / 1.602176621e6 for ii in range(data["cells"].shape[0]): vol = np.linalg.det(np.reshape(data["cells"][ii], [3, 3])) data["virials"][ii] *= v_pref * vol data = uniq_atom_names(data) return data